/*
 * spi.c
 *
 * Copyright 2023 dh33ex <dh33ex@riseup.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA or see <http://www.gnu.org/licenses/>.
 *
 *
 */

#ifndef __msp430_h_
    #include <msp430.h>
#endif
#include "spi.h"

#define CSDIR       P1DIR
#define CSOUT       P1OUT
#define CSPIN       BIT3

void spi_init(void) {
    // setup SPI
    UCB0CTL1 |= UCSWRST;        // put B0 into reset
    UCB0CTL1 |= UCSSEL_2;       // choose SMCLK
    UCB0BR0 = 5;                // CLK = SMCLK / 5 = 1 MHz / 5 = 200 kHz
    UCB0BR1 = 0;
    
    UCB0CTL0 |= UCSYNC | UCMSB | UCMST | UCCKPH;
    
    // MOSI, MISO and CLK setup
    P1SEL |= BIT5;              // P1.5 use CLK (11)
    P1SEL2 |= BIT5;
    
    P1SEL |= BIT6;              // P1.6 use MISO (11)
    P1SEL2 |= BIT6;
    
    P1SEL |= BIT7;              // P1.7 use MOSI (11)
    P1SEL2 |= BIT7;
    
    // CS pin setup
    // WARNING: if P2.6 or P2.7 used, additional setup required!
    CSDIR |= CSPIN;                 // set pin to output
    CSOUT &= ~CSPIN;                // disable pin initially
    
    UCB0CTL1 &= ~UCSWRST;
}

BYTE spi_send(BYTE byte) {
    while (UCB0STAT & UCBUSY);  // wait until SPI is free
    UCB0TXBUF = byte;           // send byte
    while (UCB0STAT & UCBUSY);  // wait until SPI free
    
    return UCB0RXBUF;           // return answer
}

BYTE spi_receive(void) {
    return spi_send(0xFF);
}

void spi_select(void) {
    CSOUT &= ~CSPIN;            // active low
}

void spi_deselect(void) {
    CSOUT |= CSPIN;             // active low
}
